using B.S.Medical.Api.Read.Application.Command.Payment;
using B.S.Medical.Domain.Doctor;
using B.S.Medical.Domain.Department;
using B.S.Medical.Domain.Medical;
using B.S.Medical.ErrorCode;
using B.S.Medical.Infrastructure.Interface;
using MediatR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using B.S.Medical.Domain.Payment;

namespace B.S.Medical.Api.Read.Application.Handler.Payment
{
    /// <summary>
    /// 查询患者待缴费项目处理器
    /// </summary>
    public class GetPatientPaymentItemsHandler : IRequestHandler<GetPatientPaymentItemsCommand, ApiResult<PatientPaymentInfoDto>>
    {
        private readonly IBaseRepository<PatientModel> _patientRepository;
        private readonly IBaseRepository<PatientBalance> _patientBalanceRepository;
        private readonly IBaseRepository<PaymentRecordModel> _paymentRecordRepository;
        private readonly IBaseRepository<DoctorModel> _doctorRepository;
        private readonly IBaseRepository<ManageModel> _departmentRepository;
        private readonly ILogger<GetPatientPaymentItemsHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        public GetPatientPaymentItemsHandler(
            IBaseRepository<PatientModel> patientRepository,
            IBaseRepository<PatientBalance> patientBalanceRepository,
            IBaseRepository<PaymentRecordModel> paymentRecordRepository,
            IBaseRepository<DoctorModel> doctorRepository,
            IBaseRepository<ManageModel> departmentRepository,
            ILogger<GetPatientPaymentItemsHandler> logger)
        {
            _patientRepository = patientRepository;
            _patientBalanceRepository = patientBalanceRepository;
            _paymentRecordRepository = paymentRecordRepository;
            _doctorRepository = doctorRepository;
            _departmentRepository = departmentRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理查询患者待缴费项目命令
        /// </summary>
        public async Task<ApiResult<PatientPaymentInfoDto>> Handle(GetPatientPaymentItemsCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation($"开始查询患者ID为 {request.PatientId} 的待缴费项目");

                // 查询患者信息
                var patient = _patientRepository.GetAll()
                    .Where(p => p.Id == request.PatientId && !p.IsDeleted)
                    .FirstOrDefault();

                if (patient == null)
                {
                    _logger.LogWarning($"未找到ID为 {request.PatientId} 的患者");
                    return new ApiResult<PatientPaymentInfoDto>
                    {
                        Code = ApiEnum.Fail,
                        Msg = "未找到指定患者"
                    };
                }

                // 查询患者余额
                var balance = _patientBalanceRepository.GetAll()
                    .Where(b => b.PatientId == request.PatientId && !b.IsDeleted)
                    .FirstOrDefault();

                decimal cardBalance = balance?.Balance ?? 0;

                // 查询待缴费项目
                var paymentRecords = _paymentRecordRepository.GetAll()
                    .Where(p => p.PatientId == request.PatientId && !p.IsDeleted && !p.IsPaid)
                    .ToList();

                // 获取相关医生和科室信息
                var doctorIds = paymentRecords.Select(p => p.DoctorId).Distinct().ToList();
                var doctors = _doctorRepository.GetAll()
                    .Where(d => doctorIds.Contains(d.Id) && !d.IsDeleted)
                    .ToDictionary(d => d.Id, d => d);

                var departmentIds = doctors.Values.Select(d => d.DepartmentId).Distinct().ToList();
                var departments = _departmentRepository.GetAll()
                    .Where(d => departmentIds.Contains(d.Id) && !d.IsDeleted)
                    .ToDictionary(d => d.Id, d => d);

                // 构建返回结果
                var result = new PatientPaymentInfoDto
                {
                    PatientId = patient.Id,
                    PatientName = patient.Name,
                    IdCard = patient.IdCard,
                    PhoneNumber = patient.Phone,
                    CardBalance = cardBalance,
                    PaymentItems = new List<PaymentItemDto>()
                };

                // 填充待缴费项目
                foreach (var record in paymentRecords)
                {
                    var doctor = doctors.GetValueOrDefault(record.DoctorId);
                    var departmentName = string.Empty;
                    
                    if (doctor != null && departments.TryGetValue(doctor.DepartmentId, out var department))
                    {
                        departmentName = department.DepartmentName;
                    }

                    result.PaymentItems.Add(new PaymentItemDto
                    {
                        Id = record.Id,
                        ItemName = record.ItemName,
                        DepartmentName = departmentName,
                        DoctorName = doctor?.DoctorName ?? string.Empty,
                        Amount = record.Amount,
                        CreatedTime = record.CreatedTime
                    });
                }

                _logger.LogInformation($"成功查询到患者 {patient.Name}(ID:{patient.Id}) 的待缴费项目，共 {result.PaymentItems.Count} 项");

                return new ApiResult<PatientPaymentInfoDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "查询成功",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"查询患者ID为 {request.PatientId} 的待缴费项目时发生错误");
                return new ApiResult<PatientPaymentInfoDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"查询失败: {ex.Message}"
                };
            }
        }
    }
} 